package com.usooft.metaTalent.core.system.service.basic;

import com.usooft.metaTalent.core.system.entity.Employee;
import com.usooft.metaTalent.core.system.entity.EmployeeRole;
import com.usooft.metaTalent.core.system.entity.Role;
import com.usooft.metaTalent.core.system.query.EmployeeRoleQuery;
import com.usooft.metaTalent.core.system.query.RoleQuery;
import com.usooft.metaTalent.core.system.service.EmployeeRoleService;
import com.usooft.metaTalent.core.system.service.RoleService;
import com.usooft.metaTalent.core.system.service.base.BaseEmployeeRoleService;
import com.usooft.metaTalent.core.system.wrapper.EmployeeRoleWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.usooft.framework.core.utils.Checks.checkNotNull;

@Service
@RequiredArgsConstructor
@Slf4j
public class BasicEmployeeRoleService extends BaseEmployeeRoleService implements EmployeeRoleService {

    private final RoleService roleService;

    @Override
    @Cacheable(value = "employeeIdToRoleIds", key = "#employee.id")
    public Set<Long> listRoleIds(Employee employee) {
        return list(EmployeeRoleQuery.builder()
                .filter(EmployeeRoleQuery.Filter.builder()
                        .employeeIdIs(employee.getId())
                        .build())
                .build())
                .stream()
                .mapToLong(EmployeeRole::getRoleId)
                .boxed()
                .collect(Collectors.toSet());
    }

    @Override
    @Transactional
    @CacheEvict(value = "employeeIdToRoleIds", key = "#employee.id")
    public void grant(Employee employee, List<? extends Role> roles) {
        checkNotNull(employee, "必须提供员工");

        // 员工已经存在的角色
        List<EmployeeRoleWrapper> currentEmployeeRoles = list(EmployeeRoleQuery.builder()
                .filter(EmployeeRoleQuery.Filter.builder()
                        .employeeIdIs(employee.getId())
                        .build())
                .build());

        // 取消角色
        Set<Long> roleIds = roles.stream().map(Role::getId).collect(Collectors.toSet());
        List<EmployeeRoleWrapper> needRemoved = currentEmployeeRoles.stream().filter(er -> !roleIds.contains(er.getRoleId())).toList();
        if (!needRemoved.isEmpty()) {
            needRemoved.forEach(this::internalDelete);
            log.info("员工 [{}] 删除角色 [{}]", employee.getName(), needRemoved.stream()
                    .map(er -> er.getRoleId().toString())
                    .collect(Collectors.joining(", ")));
        }

        // 新增角色
        Set<Long> originalRoleIds = currentEmployeeRoles.stream().map(EmployeeRole::getRoleId).collect(Collectors.toSet());
        Long[] newRoleIds = roleIds.stream()
                .filter(roleId -> !originalRoleIds.contains(roleId))
                .toArray(Long[]::new);
        if (newRoleIds.length > 0) {
            List<? extends Role> needAddedRoles = roleService.list(RoleQuery.builder()
                    .filter(RoleQuery.Filter.builder()
                            .idIn(newRoleIds)
                            .build())
                    .build());
            needAddedRoles.forEach(role -> {
                internalAdd(employee.getId(), role);
            });
            log.info("员工 [{}] 新增角色 [{}]", employee.getName(), needAddedRoles.stream()
                    .map(Role::getName)
                    .collect(Collectors.joining(", ")));
        }
    }

    // region 自动生成
    // endregion
}